<script setup lang="ts">
  import { computed, ref, h } from 'vue';
  import type { ProFormProps, FormActionType } from '@/components/QueryFilter';
  import QueryFilter from '@/components/QueryFilter';
  import TableToolbar from './components/TableToolbar.vue';
  import { usePagination, PaginationProps } from './hooks/usePagination';
  import { ProColumns, TagItem } from './types/index';
  import useDataSource from './hooks/useDataSource';
  import { NTag, NSpace } from 'naive-ui';
  import type { DataTableProps } from 'naive-ui';

  export interface ProTableProps {
    title?: string;
    titleTooltip?: string;
    pagination?: PaginationProps;
    rowKey?: (rowData: object) => number | string;
    columns?: ProColumns[];
    request?: (params: any) => void;
    tableProps?: DataTableProps;
    search?: ProFormProps;
  }
  const props = withDefaults(defineProps<ProTableProps>(), {});
  const tableRef = ref();
  const formRef = ref<FormActionType>();
  const loading = ref(false);
  const setLoading = (value: boolean) => (loading.value = value);
  const { pagination, setPagination } = usePagination(props.pagination);
  const { dataSource, reload } = useDataSource(props, {
    formRef,
    pagination,
    setPagination,
    setLoading,
  });

  const getColumns = computed(() => {
    return props.columns?.map((val) => {
      const titleLen = val.title?.length;
      const currentPage = pagination.value.page ?? 1;
      const pageSize = pagination.value.pageSize ?? 10;
      const width = titleLen ? titleLen * 15 + 30 : undefined;
      const obj = {
        ellipsis: val.render ? true : { tooltip: true },
        render:
          val.key === 'dataIndex'
            ? (_row: any, index: number) => (currentPage - 1) * pageSize + index + 1
            : undefined,
        width: val.key === 'dataIndex' ? 30 : width,
        ...val,
      };
      if (val.isTag) {
        obj.render = (row: any, index: number) => {
          const map = val.render ? val.render(row, index) ?? [] : [];
          const tags = map as TagItem[];
          const Tags = tags?.map((item, itemIndex) => {
            const { size = 'small', key = itemIndex, type = 'info' } = item;
            return h(
              NTag,
              {
                size,
                key,
                type,
              },
              () => item.value
            );
          });
          return h(
            NSpace,
            {
              size: [6, 3],
            },
            () => Tags
          );
        };
      }
      return obj;
    });
  });

  const tablePropsInfo = computed(() => {
    return {
      loading: loading.value,
      rowKey: () => 'key',
      data: dataSource.value,
      ...props,
      ...props.tableProps,
      columns: getColumns.value,
      // 'max-height': maxHeight,
    };
  });

  // 页码切换
  const updatePage = (page: number) => {
    setPagination({ page });
    reload();
  };

  // 分页数量切换
  const updatePageSize = (pageSize: number) => {
    setPagination({ pageSize });
    reload();
  };

  // 向外暴露的方法
  defineExpose({
    reload,
    form: formRef.value,
    tableRef: tableRef.value,
  });
</script>
<template>
  <n-card :bordered="false" class="mb-10px proCard pt-16px" v-if="search">
    <QueryFilter
      :columns="search?.columns"
      :submitter="search?.submitter"
      @on-finish="reload"
      v-bind="search.formProps"
      ref="formRef"
    >
      <template #statusSlot="{ model, field }"><n-input v-model:value="model[field]" /></template>
    </QueryFilter>
  </n-card>
  <n-card :bordered="false" class="proCard">
    <TableToolbar :title="title" :title-tooltip="titleTooltip">
      <template #tableTitle>
        <slot name="tableTitle"></slot>
      </template>
      <template #toolbar>
        <slot name="toolbar"></slot>
      </template>
    </TableToolbar>
    <div class="s-table">
      <n-data-table
        ref="tableRef"
        v-bind="tablePropsInfo"
        :pagination="pagination"
        @update:page="updatePage"
        @update:page-size="updatePageSize"
      >
        <template #[item]="data" v-for="item in Object.keys($slots)" :key="item">
          <slot :name="item" v-bind="data"></slot>
        </template>
      </n-data-table>
    </div>
  </n-card>
</template>

<style scoped></style>
